package com.game;

import java.util.Vector;
import java.lang.Math;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;

import android.graphics.Point;
import android.graphics.PointF;



public class Laser 
{
	Vector<Point> mPoints;
	Vector<Point> mPointsAlpha;
	Vector<Point> mPointsBetha;
	PointF heading;
	BallManager mBallManager;
	BackgroundMirror mBackgroundMirror;
	Vector<MirrorBall> mMirrorBallsReference;
	Vector<PowerUp> mPUPReference;
	Vector<BallBool> mColiding;
	int speed;
	final int PointCount = 40;
	Bitmap img,edge, head, head2, head3, head4, head5;
	int separation;
	
	public int timeCounter;
	private int lifeTime;
	public boolean extraLaser;
	public boolean inactive;

	
	Laser(Context context, Vector<MirrorBall> mbref, BallManager ballmanager, BackgroundMirror backgroundmirror, 
			int imgRef, int edgeRef, int headRef, int headRef2, int headRef3, int headRef4, int headRef5,
			Vector<PowerUp> pups)
	{
		mBallManager = ballmanager;
		mBackgroundMirror = backgroundmirror;
		mMirrorBallsReference = mbref;
		mPUPReference = pups;
		img = BitmapFactory.decodeResource(context.getResources(), imgRef);
		edge = BitmapFactory.decodeResource(context.getResources(), edgeRef);
		head = BitmapFactory.decodeResource(context.getResources(), headRef);
		head2 = BitmapFactory.decodeResource(context.getResources(), headRef2);
		head3 = BitmapFactory.decodeResource(context.getResources(), headRef3);
		head4 = BitmapFactory.decodeResource(context.getResources(), headRef4);
		head5 = BitmapFactory.decodeResource(context.getResources(), headRef5);
		mPoints = new Vector<Point>();
		mPointsAlpha = new Vector<Point>();
		mPointsBetha = new Vector<Point>();
		mColiding = new Vector<BallBool>();
		mColiding.add(new BallBool(false));
		mColiding.add(new BallBool(false));		
		heading = new PointF();
		
		separation = 2;
		
		Reset();
		
		lifeTime = 400;
		timeCounter = 0;
		extraLaser = false;
		inactive = false;
		
	}
	
	public void Reset()
	{
		mPoints.clear();
		mPointsAlpha.clear();
		mPointsBetha.clear();
		
		int defaultY = 200;
		int defaultStartX = 40;
		Point auxPoint, auxPointTheta;
		for(int i = 0; i < PointCount; i++)
		{
			auxPoint = new Point();
			auxPoint.x = defaultStartX + 2*i;
			auxPoint.y = defaultY;	
			mPoints.add(auxPoint);
			
			auxPointTheta = new Point();
			auxPointTheta.x = auxPoint.x +separation;
			auxPointTheta.y = auxPoint.y +separation;
			mPointsAlpha.add(auxPointTheta);
			
			auxPointTheta = new Point();
			auxPointTheta.x = auxPoint.x +separation;
			auxPointTheta.y = auxPoint.y -separation;
			mPointsBetha.add(auxPointTheta);
			
		}
		
		heading.x = 20;
		heading.y = 20;
		
		speed = 5;
	}
	
	public void Update()
	{
		if(inactive) return;
		Colide();
		Move();
	}
	

	public void Colide()
	{

		// Against the mirrors
		for(MirrorBall mirror : mMirrorBallsReference)
		{			
			if(	Math.abs(mPoints.elementAt(0).x- mirror.getCenterX()) < mirror.getRadius() &&
				Math.abs(mPoints.elementAt(0).y- mirror.getCenterY()) < mirror.getRadius() &&
				mirror.getMirrorSet())
			{
				// Is near
				
				if(! mColiding.elementAt(mirror.ID).Coliding )
				{
					mColiding.elementAt(mirror.ID).Coliding  = true;				
					
					//The mirror is set
					PointF normalHeading, tangentHeading, normalToCollisionPlane;
					normalToCollisionPlane = new PointF();
					normalHeading = new PointF();
					tangentHeading = new PointF();
					
					normalToCollisionPlane.x = 0; 	normalToCollisionPlane.y = 0;  
					normalHeading.x = 0; 			normalHeading.y = 0;
					tangentHeading.x = 0; 			tangentHeading.y = 0;
					
					// Get the line connecting the laser tip and the mirror center
					normalToCollisionPlane.x = mirror.getCenterX() - getCenterOfPointX();
					normalToCollisionPlane.y = mirror.getCenterY() - getCenterOfPointY();
					
					// Get the normal component of the heading. This is done by projecting it
					// on the line that connects the center of the ball to the tip of the laser
					float proyectionLength =0;
					proyectionLength = 	heading.x*normalToCollisionPlane.x + 
										heading.y*normalToCollisionPlane.y;
					proyectionLength = proyectionLength / normalToCollisionPlane.length();
					
					// Normalize the normalToColPlane to get the unitary vector
					normalToCollisionPlane.x = normalToCollisionPlane.x/normalToCollisionPlane.length();
					normalToCollisionPlane.y = normalToCollisionPlane.y/normalToCollisionPlane.length();
					
					normalHeading.x = proyectionLength*normalToCollisionPlane.x;
					normalHeading.y = proyectionLength*normalToCollisionPlane.y; // Got it!!
					
					// Now we get the tangent, by simple vector decomposition: v = v.t+v.n
					tangentHeading.x = heading.x - normalHeading.x;
					tangentHeading.y = heading.y - normalHeading.y;
					
					// Finally, add to the tangent the negated normal to reflect away from the mirror
					heading.x =  (tangentHeading.x  - normalHeading.x);
					heading.y =  (tangentHeading.y  - normalHeading.y);				
										
				}
			}
			else
			{mColiding.elementAt(mirror.ID).Coliding  = false; }
		}
		
		// Against the balls
		for( ColorBall ball: mBallManager.balls)
		{
			if(	Math.abs(mPoints.elementAt(0).x- ball.getCenterX()) < ball.getRadius() &&
				Math.abs(mPoints.elementAt(0).y- ball.getCenterY()) < ball.getRadius())
			{
				ball.Explode();
			}
		}
		
		// Against the borders
		if(getLeft() < mBackgroundMirror.getLeftLimit())
		{
			setLeft(mBackgroundMirror.getLeftLimit());
			heading.x = (-1)*heading.x;
		}
		else if (getRight() > mBackgroundMirror.getRightLimit())
		{		
			setRight(mBackgroundMirror.getRightLimit());
			heading.x = (-1)*heading.x;
		}
		
		if(getTop() < mBackgroundMirror.getTopLimit())
		{			
			setTop(mBackgroundMirror.getTopLimit());
			heading.y = (-1)*heading.y;
		}
		else if (getBottom() > mBackgroundMirror.getBottomLimit())
		{
			setBottom(mBackgroundMirror.getBottomLimit());
			heading.y = (-1)*heading.y;
		}
		
		// against PUPs
		for(PowerUp PUP : mPUPReference)
		{
			if(PUP.size.contains(getCenterOfPointX(), getCenterOfPointY()))
			{
				PUP.DoPowerUp();
			}
		}
	}
	
	public void Move()
	{
		// Update the position of each point to the one in front, except the lead
		for(int i = PointCount-1; i >0; i--)
		{
			mPoints.elementAt(i).x = mPoints.elementAt(i-1).x;
			mPoints.elementAt(i).y = mPoints.elementAt(i-1).y;
			
			mPointsAlpha.elementAt(i).x = mPointsAlpha.elementAt(i-1).x;
			mPointsAlpha.elementAt(i).y = mPointsAlpha.elementAt(i-1).y;
			
			mPointsBetha.elementAt(i).x = mPointsBetha.elementAt(i-1).x;
			mPointsBetha.elementAt(i).y = mPointsBetha.elementAt(i-1).y;
			
		}
		
		
		// Update the first element
		float length = heading.length(); //(float)Math.sqrt(heading.x*heading.x + heading.y*heading.y);

		float normalizedx = (heading.x/length);
		float normalizedy = (heading.y/length);
		
		normalizedx *= speed;
		normalizedy *= speed;
		
		mPoints.elementAt(0).x += normalizedx;
		mPoints.elementAt(0).y += normalizedy;
		
		mPointsAlpha.elementAt(0).x = mPoints.elementAt(0).x+separation;
		mPointsAlpha.elementAt(0).y = mPoints.elementAt(0).y+separation;
		
		mPointsAlpha.elementAt(0).x = mPoints.elementAt(0).x+separation;
		mPointsAlpha.elementAt(0).y = mPoints.elementAt(0).y-separation;
	}
	
	public void onDraw(Canvas canvas)
	{
		if(inactive) return;
		
		for(Point curPoint : mPointsAlpha)
		{			
			canvas.drawBitmap(edge, curPoint.x, curPoint.y, null);
		}

		// Backwards drawing so it doesn't get in the way.
		int counter = mPoints.size();
		Point curPointM;
		for(int i = mPoints.size()-1; i>= 0;i--)
		{
			curPointM = mPoints.elementAt(i);
			
			switch (counter) {
			case 0: canvas.drawBitmap(head, curPointM.x, curPointM.y, null);	break;
			case 1: canvas.drawBitmap(head2, curPointM.x, curPointM.y, null);	break;
			case 2: canvas.drawBitmap(head3, curPointM.x, curPointM.y, null);	break;
			case 3: canvas.drawBitmap(head4, curPointM.x, curPointM.y, null);	break;
			case 4: canvas.drawBitmap(head5, curPointM.x, curPointM.y, null);	break;

			default:
				canvas.drawBitmap(img, curPointM.x, curPointM.y, null);
				break;
			}
			counter--;
		}
		
		
		for(Point curPoint : mPointsBetha)
		{			
			canvas.drawBitmap(edge, curPoint.x, curPoint.y, null);
		}
	}

	public boolean ReadyToDie()
	{
		timeCounter++;
		if(timeCounter>=lifeTime)
		{
			return true;
		}
		else return false;		
	}
	
	public int getLeft() 	{return mPoints.elementAt(0).x;}
	public int getRight() 	{return mPoints.elementAt(0).x + img.getWidth();}
	public int getTop()		{return mPoints.elementAt(0).y;}
	public int getBottom() 	{return mPoints.elementAt(0).y + img.getHeight();}
	
	public void setLeft(int limit) 	{ mPoints.elementAt(0).x = limit;}
	public void setRight(int limit) 	{mPoints.elementAt(0).x= limit - img.getWidth();}
	public void setTop(int limit)    {mPoints.elementAt(0).y = limit;}
	public void setBottom(int limit) {mPoints.elementAt(0).y = limit- img.getHeight();}
	
	public int getCenterOfPointX()	{return mPoints.elementAt(0).x + img.getWidth()/2;	}	
	public int getCenterOfPointY()	{return mPoints.elementAt(0).y + img.getHeight()/2;	}
	
}




/*
 * int counter = 0;
		for(Point curPoint : mPoints)
		{
			switch (counter) {
			case 0: canvas.drawBitmap(head, curPoint.x, curPoint.y, null);	break;
			case 1: canvas.drawBitmap(head2, curPoint.x, curPoint.y, null);	break;
			case 2: canvas.drawBitmap(head3, curPoint.x, curPoint.y, null);	break;
			case 3: canvas.drawBitmap(head4, curPoint.x, curPoint.y, null);	break;
			case 4: canvas.drawBitmap(head5, curPoint.x, curPoint.y, null);	break;

			default:
				canvas.drawBitmap(img, curPoint.x, curPoint.y, null);
				break;
			}

			counter++;
		}
 * */

 